<?php
/**
 * Hols class Image_Lib_Color
 *
 * @author daantimmer
 *
 * @package Library
 * @subpackage Image
 */

/**
 * Wrapper class around an RGB color
 *
 * @author daantimmer
 */
class Image_Lib_Color{

	private $r,$g,$b;

	/**
	 * Either accepts an array(r,g,b) or an
	 * integer(0x00RRGGBB)
	 *
	 * @param mixed $color
	 * @return Image_Lib_Color
	 */
	public function __construct($color = 0){
		if(is_array($color)){
			$this->r = $color[0];
			$this->g = $color[1];
			$this->b = $color[2];
		}else{
			$this->r = ($color >> 16) & 0xff;
			$this->g = ($color >> 8)  & 0xff;
			$this->b = ($color)       & 0xff;
		}
	}

	/**
	 * Returns red
	 *
	 * @return integer
	 */
	public function getRed(){
		return $this->r;
	}

	/**
	 * Returns green
	 *
	 * @return integer
	 */
	public function getGreen(){
		return $this->g;
	}

	/**
	 * Returns blue
	 *
	 * @return integer
	 */
	public function getBlue(){
		return $this->b;
	}

	/**
	 * Converts R,G,B, into HSV
	 *
	 * @param $r
	 * @param $g
	 * @param $b
	 * @param $hsv by reference
	 * @return void
	 */
	public static function rgb2hsv($r,$g,$b,&$hsv){
		$r = $r / 255.0;
		$g = $g / 255.0;
		$b = $b / 255.0;

		$H = 0;
		$S = 0;
		$V = 0;

		$min = min(min($r, $g),$b);
		$max = max(max($r, $g),$b);
		$delta = $max - $min;

		$V = $max;

		if($delta == 0){
			$H = 0;
			$S = 0;
		}else{
			$S = $delta / $max;

			$dR = ((($max - $r) / 6) + ($delta / 2)) / $delta;
			$dG = ((($max - $g) / 6) + ($delta / 2)) / $delta;
			$dB = ((($max - $b) / 6) + ($delta / 2)) / $delta;

			if ($r == $max)
			$H = $dB - $dG;
			else if($g == $max)
			$H = (1/3) + $dR - $dB;
			else
			$H = (2/3) + $dG - $dR;

			if ($H < 0)
			$H += 1;
			if ($H > 1)
			$H -= 1;
		}

		$hsv[0] = $H;
		$hsv[1] = $S;
		$hsv[2] = $V;
	}

	/**
	 * Converts $hsv to RGB
	 *
	 * @param array $hsv
	 * @return array rgb
	 */
	public static function hsv2rgb(array $hsv){
		$h = max(0, min(1, $hsv[0]));
		$s = max(0, min(1, $hsv[1]));
		$v = max(0, min(1, $hsv[2]));
		$r = $g = $b = 0;

		if($s == 0){
			return array(round($v * 255), round($v * 255), round($v * 255));
		}
		
		$h *= 360;

		$h /= 60;
		$i = floor($h);
		$f = $h - $i;
		$p = $v * (1 - $s);
		$q = $v * (1 - $s * $f);
		$t = $v * (1 - $s * (1 - $f));

		switch($i) {
			case 0:
				$r = $v;
				$g = $t;
				$b = $p;
				break;

			case 1:
				$r = $q;
				$g = $v;
				$b = $p;
				break;

			case 2:
				$r = $p;
				$g = $v;
				$b = $t;
				break;

			case 3:
				$r = $p;
				$g = $q;
				$b = $v;
				break;

			case 4:
				$r = $t;
				$g = $p;
				$b = $v;
				break;

			default: // case 5:
				$r = $v;
				$g = $p;
				$b = $q;
		}
		
		return array(round($r * 255), round($g * 255), round($b * 255));
	}
	
	/**
	 * returns this colors RGB value as a human-readable string
	 *
	 * @return string
	 */
	public function __toString(){
		return "{r:{$this->r}, g:{$this->g}, b:{$this->b}}";
	}
}